package com.yangxd.auth;


import com.yangxd.hospital.service.auth.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

/**
 * @Author: yangxudong
 * @Date: 2021/4/15 11:06
 * @Version 1.0
 */
@Configuration     //配置类
@EnableWebSecurity //开启认证功能
@EnableGlobalMethodSecurity(prePostEnabled = true)  //使用全局方法
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private PasswordEncoder passwordEncoder;
    /**
     *登录成功的处理方案
     */
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    /**
     *登录失败的处理方案
     * @return
     */
    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    /**
     * 用户未登录访问其他页面
     */
    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    /**
     * 无权限访问某页面
     */
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    /**
     * 注销操作
     */
    @Autowired
    private MyLogoutHandler myLogoutHandler;

    /**
     * 注销成功
     */
    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    /**
     * session超时管理
     */
    @Autowired
    private MyInvalidSessionStrategy myInvalidSessionStrategy;
    /**
     * 被挤下线的处理
     */
    @Autowired
    private MyExpiredSessionStrategy myExpiredSessionStrategy;
    //    protected WebSecurityConfig() {
//        super();
//    }
    @Bean
    public UserDetailsService myUserService(){
        return new UserDetailsServiceImpl();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        //使用hash加密方式
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);

        auth.userDetailsService(myUserService()).passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //  super.configure(web);
        //那些文件夹忽略，静态资源放行
        web.ignoring().antMatchers(HttpMethod.GET,
                "/favicon.ico",
                "/**/*.png",
                "/**/*.ttf",
                "/*.html",
                "/**/*.css",
                "/**/*.js"

                );

        web.ignoring().antMatchers(HttpMethod.POST,"/uploadImgFile","/hospital/user/saveUser",
                "/hospital/role-user/saveRoleUser");



    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        //需要放行的url在这里配置,必须要放行/login和/login.html,不然会报错
                .antMatchers("/login","/login.html").permitAll()
                .antMatchers(HttpMethod.POST,"/uploadImgFile").permitAll()
                .antMatchers(HttpMethod.POST,"/hospital/role-user/saveRoleUser").permitAll()
                .antMatchers(HttpMethod.POST,"/hospital/user/saveUser").permitAll()
                .antMatchers(HttpMethod.GET,"/swagger-ui.html").permitAll()
                .antMatchers(HttpMethod.GET,"/doc.html").permitAll()
                .antMatchers(HttpMethod.GET,"/webjars/**").permitAll()
                .antMatchers(HttpMethod.GET,"/v2/**").permitAll()
                .antMatchers(HttpMethod.GET,"/swagger-resources/**").permitAll()
                .antMatchers("/users","/roles")
                //.hasAuthority("ROLE_user")
                .hasAnyAuthority("ROLE_user","ROLE_admin")
                .antMatchers("/menus","/others")
                //.hasRole("admin")
                .hasAnyRole("admin")
                .anyRequest()
                .authenticated()
                .and()
                // 设置登陆页
                .formLogin().loginPage("/login.html")
                //登录表单form中action的地址，也就是处理认证请求的路径
                .loginProcessingUrl("/login")
                //登录表单form中用户名输入框input的name名，不修改的话默认是username
                .usernameParameter("userName")
                //登录表单form中密码输入框input的name名，不修改的话默认是password
                .passwordParameter("password")
                //登录认证成功后默认转跳的路径
                //.defaultSuccessUrl("/home").permitAll()
                // 登录失败Url
                //.failureUrl("/login/error");
                .successHandler(myAuthenticationSuccessHandler)
                .failureHandler(myAuthenticationFailureHandler)
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDeniedHandler)
                .and()
                //允许注销操作
                .logout().permitAll()
                .addLogoutHandler(myLogoutHandler)
                .logoutSuccessHandler(myLogoutSuccessHandler)
                //删除登录后的cookie
                //.deleteCookies("JSESSIONID");
                .and()
                .sessionManagement().invalidSessionStrategy(myInvalidSessionStrategy)
                //最大登录数为1
                .maximumSessions(1)
                //不允许其他人登录
                .maxSessionsPreventsLogin(false)
                .expiredSessionStrategy(myExpiredSessionStrategy);

//        //第1步：解决跨域问题。cors 预检请求放行,让Spring security 放行所有preflight request（cors 预检请求）
//        http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
////
////        //第2步：让Security永远不会创建HttpSession，它不会使用HttpSession来获取SecurityContext
//        http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
//                .and().headers().cacheControl();
//
//        //第3步：请求权限配置
//        http.authorizeRequests()
//                //.antMatchers("/**").permitAll()
//                .antMatchers(HttpMethod.GET,"/swagger-ui.html").permitAll()
//                .antMatchers(HttpMethod.GET,"/doc.html").permitAll()
//                .antMatchers(HttpMethod.GET,"/webjars/**").permitAll()
//                .antMatchers(HttpMethod.GET,"/v2/**").permitAll()
//                .antMatchers(HttpMethod.GET,"/swagger-resources/**").permitAll()
//                .antMatchers(HttpMethod.GET,"/users/getUserInfo").permitAll()
//                .antMatchers(HttpMethod.POST,"/login").permitAll();
//             //   .anyRequest().access("@dynamicPermission.hasPermission(request,authentication)");
//
//        //关闭防火墙
          http.cors().and().csrf().disable();
//        //第4步：拦截token，并检测。在 UsernamePasswordAuthenticationFilter 之前添加 JwtAuthenticationTokenFilter
//      //  http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//
//        //第5步：处理异常情况：认证失败和权限不足
//      //  http.exceptionHandling().authenticationEntryPoint(myAuthenticationEntryPoint).accessDeniedHandler(myAccessDeniedHandler);
//
//        //第6步：登录,因为使用前端发送JSON方式进行登录，所以登录模式不设置也是可以的。
//        http.formLogin().loginPage("/login").usernameParameter("userName").passwordParameter("password").successHandler(myAuthenticationSuccessHandler).failureHandler(myAuthenticationFailureHandler);
//
//        //第七步：设置会话管理：同一账号同时登录最大用户数,会话失效(账号被挤下线)处理逻辑
//        http.sessionManagement()
//                .maximumSessions(1)
//                .maxSessionsPreventsLogin(false)
//                .expiredSessionStrategy(myExpiredSessionStrategy);
//
//        //第8步：退出
//        http.logout().addLogoutHandler(myLogoutHandler).logoutSuccessHandler(myLogoutSuccessHandler).deleteCookies("JSESSIONID");



    }
}
